.TITLE DTDRV .IDENT /10/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; VERSION 10 ; ; D. N. CUTLER 1-DEC-73 ; ; PREVIOUSLY MODIFIED BY: ; ; P. J. BEZEREDI ; D. N. CUTLER ; C. A. D'ELIA ; F. L. STRAIGHT ; T. J. MILLER ; ; MODIFIED BY: ; ; P. J. BEZEREDI 13-MAY-77 ; ; PB029 -- I/O DATA STRUCTURE CHANGES. ; ; P. J. BEZEREDI 14-DEC-77 ; ; PB050 -- REMOVE UNNEEDED CONDITIONALS FOR RSX-11M+. ; ; E. L. BAATZ 18-JUN-78 ; ; EB148 -- REMOVE EXPLICIT PS REFERENCE. ; ; P. J. BEZEREDI 05-JUL-78 ; ; PB079 -- INSURE R2 CONTAINS CSR ADDRESS BEFORE LOGGING ; AN ERROR. ; ; P. J. BEZEREDI 18-JUL-78 ; ; PB081 -- EXPAND I/O ACTIVITY INFORMATION REPORTED AT ; TIME OF AN ERROR. ; ; P. J. BEZEREDI 21-AUG-78 ; ; PB083 -- ADDITION OF SOFTWARE VOLUME VALID SUPPORT. ; ; TC11 DECTAPE CONTROLLER DRIVER ; ; MACRO LIBRARY CALLS ; .MCALL ABODF$,HWDDF$,PKTDF$ ABODF$ ;DEFINE TASK ABORT CODES HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS ; ; EQUATED SYMBOLS ; WAIT=100000 ;WAITING TO SELECT UNIT (1=YES) ABRT=40000 ;ABORT CURRENT FUNCTION (1=YES) RETRY=5. ;ERROR RETRY COUNT ; ; LOCAL DATA ; ; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER) ; ; DIAGNOSTIC FUNCTIONS IO.RNF AND IO.RNR USE BIT 7 OF RTTBL AS ; A FLAG FOR INTERRUPT SERVICING. RTTBL: .BLKW T$$C11 ;ERROR RETRY COUNT AND DRIVE RESET FLAG ;+ ; DRIVER DISPATCH TABLE ;- DDT$ DT,T$$C11 ;GENERATE DISPATCH TABLE ;+ ; **-DTINI-TC11 DECTAPE CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUE ; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE ; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN A ; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER I ; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER ; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; OUTPUTS: ; ; IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WA ; ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OP ; ATION IS INITIATED. ;- .ENABL LSB DTINI: GTPKT$ DT,T$$C11,DTPWF ;GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK. ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; TC11 DECTAPE I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK. ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER. ; WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADE ; WD. 05 -- I/O FUNCTION CODE (IO.RLB,IO.RLV,IO.WLB, OR IO.WLV). ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 14000 ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE. ; WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER. ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER. ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED. ; WD. 15 -- NOT USED. ; WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED. ; WD. 17 -- LOGICAL BLOCK NUMBER OF I/O REQUEST. ; WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLK. ADDRESS ; WD. 21 -- DIAGNOSTIC REG. BLK. ADDRESS (REAL OR DISPL. + 140000) ; CALL $VOLVD ;VALIDATE VOLUME VALID BCS 8$ ;IF CS WE FAILED TST R0 ;TRANSFER FUNCTION? BPL 8$ ;IF PL NO .IF DF M$$EXT CALL $STMAP ;SET UP UNIBUS MAPPING ADDRESS .ENDC MOV #<8.*256.>+RETRY,RTTBL(R3) ;SET ROCK AND RETRY COUNTS MOV R1,R0 ;COPY I/O PACKET ADDRESS ADD #I.FCN,R0 ;POINT TO FUNCTION CODE BITB #IQ.UMD,(R0) ;DIAGNOSTIC FUNCTION CALL? BEQ 4$ ;IF EQ NO CLRB RTTBL(R3) ;NO RETRIES FOR DIAGNOSTIC OPERATIONS CMP #IO.RNF!IQ.UMD,(R0) ;READ BLOCK FORWARD? BNE 2$ ;IF NE NO MOV #IO.RLB!IQ.UMD,(R0) ;CONVERT TO READ LOGICAL FORWARD BR 3$ ; 2$: CMP #IO.RNR!IQ.UMD,(R0) ;READ BLOCK REVERSE? BNE 4$ ;IF NE NO MOV #IO.RLV!IQ.UMD,(R0) ;CONVERT TO READ LOGICAL REVERSE 3$: BIS #200,RTTBL(R3) ;SET READ BLOCK NUMBER FLAG 4$: MOV #IE.IFC&377,R0 ;ASSUME ILLEGAL FUNCTION MOV R5,R3 ;COPY ADDRESS OF UCB ADD #U.BUF+1,R3 ;POINT TO HIGH BYTE OF MEM.EXT WORD MOVB R2,(R3) ;INSERT DRIVE NUMBER BISB #105,-(R3) ;ASSUME READ LOGICAL FUNCTION CMPB #IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION? BHIS 9$ ;IF HIS FUNCTION IS LEGAL 8$: JMP 195$ ;ILLEGAL FUNCTION 9$: BEQ 10$ ;IF EQ FUNCTION IS READ BIS #10,(R3) ;CONVERT TO WRITE LOGICAL FUNCTION 10$: BIT #IO.WLV&377,I.FCN(R1) ;REVERSE DIRECTION? BEQ 20$ ;IF EQ NO BIS #4000,(R3) ;SET REVERSE DIRECTION BIT 20$: CLRB U.CW2+1(R5) ;CLEAR ABORT FLAG CALL $BLKCK ;CHECK LOGICAL BLOCK NUMBER MOV R0,U.PRM(R5) ;SAVE LOGICAL BLOCK NUMBER ; ; INITIATE I/O OPERATION ; 30$: ;REF LABEL .IF DF M$$EXT CALL $MPUBM ;MAP UNIBUS TO TRANSFER .ENDC MOV S.CSR(R4),R0 ;GET ADDRESS OF CSR CMP (R0)+,(R0)+ ;POINT TO BUFFER ADDRESS REGISTER MOV U.BUF+2(R5),(R0) ;INSERT BUFFER ADDRESS MOV U.CNT(R5),-(R0) ;INSERT LENGTH OF TRANSFER IN BYTES CLR U.PRM+2(R5) ;CLEAR FINAL ERROR STATUS ROR (R0) ;CONVERT LENGTH TO WORD COUNT NEG (R0) ;MAKE NEGATIVE WORD COUNT MOVB U.BUF+1(R5),-(R0) ;INSERT UNIT AND DIRECTION BIT BIS #WAIT,U.CW2(R5) ;SET WAITING TO SELECT UNIT MOVB #11,-(R0) ;STOP TRANSPORT (SELECT UNIT) 35$: BIT #100200,(R0) ;SELECT ERROR? BMI 40$ ;IF MI YES BEQ 35$ ;IF EQ DRIVE NOT SELECTED BIC #WAIT,U.CW2(R5) ;CLEAR WAITING TO SELECT UNIT MOVB S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT CALL $BMSET ;INDICATE I/O IS ACTIVE BISB #S3.SIP,S.ST3(R4) ;;;SHOW SEARCH IN PROGRESS MOVB #103,(R0) ;START SEARCH FOR BLOCK. ; ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAU ; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDIT ; THAT COULD EXIST IN RESTARTING THE I/O OPERATION. ; DTPWF: RETURN ; ; ; OUTPUT SELECT ERROR MESSAGE ; 40$: MOV #T.NDSE,R0 ;SET FOR DEVICE SELECT ERROR MESSAGE MOVB #1,S.CTM(R4) ;RESET CURRENT DEVICE TIMEOUT COUNT DECB S.STS(R4) ;TIME TO OUTPUT MESSAGE? BNE DTPWF ;IF NE NO MOVB #15.,S.STS(R4) ;SET TO OUTPUT NEXT MESSAGE IN 15. SECON CALLR $DVMSG ;OUTPUT MESSAGE ; ; CANCEL I/O OPERATION - FORCE I/O TO COMPLETE IF DEVICE NOT READY ; DTCAN: CMP R1,I.TCB(R0) ;;;REQUEST FOR CURRENT TASK? BNE 50$ ;;;IF NE NO BIS #ABRT,U.CW2(R5) ;;;SET FOR ABORT IF DEVICE NOT READY 50$: RETURN ;;; ; ; DEVICE TIMEOUT USUALLY OCCURS BECAUSE THE DRIVER IS WAITING TO ; SELECT A UNIT. TIMEOUTS MAY ALSO OCCUR AS A RESULT OF A HARDWARE ; FAILURE OR A POWERFAILURE. ; DTOUT: MOV S.PKT(R4),R1 ;;;GET I/O PACKET ADDRESS BITB #IQ.UMD,I.FCN(R1) ;;;DIAGNOSTIC FUNCTION CALL? BNE 165$ ;;;IF NE YES MOV U.CW2(R5),R1 ;;;WAITING TO SELECT A UNIT? BMI 55$ ;;;IF MI YES CALL $DTOER ;;;LOG DEVICE TIMEOUT 55$: MTPS #0 ;;;ALLOW DEVICE INTERRUPTS MOV #IE.ABO&377,R0 ;ASSUME REQUEST IS TO BE ABORTED ASL R1 ;ABORT REQUEST? BPL 30$ ;IF PL NO JMP 190$ ;ABORT REQUEST ;+ ; **-$DTINT-TC11 DECTAPE CONTROLLER INTERUPTS ;- INTSE$ DT,PR6,T$$C11 ;;;SAVE REGISTERS AND SET PRIORITY MOV R3,-(SP) ;;;SAVE R3 MOV U.SCB(R5),R3 ;;;GET ADDRESS OF STATUS CONTROL BLOCK MOVB S.ITM(R3),S.CTM(R3) ;;;RESET CURRENT DEVICE TIMEOUT COUN MOV S.CSR(R3),R3 ;;;GET ADDRESS OF COMMAND REGISTER TSTB RTTBL(R4) ;DIAGNOSTIC READ BLOCK NO.? BMI 150$ ;IF MI YES BIT #2,(R3) ;;;BLOCK SEARCH IN PROGRESS? BEQ 150$ ;;;IF EQ NO TST (R3) ;;;SEARCH ERROR? BPL 70$ ;;;IF PL NO TST -(R3) ;;;END ZONE? BMI 110$ ;;;IF MI YES BIT #20000,(R3)+ ;;;MARK TRACK ERROR? BNE 120$ ;;;IF NE YES-TRY TO BYPASS IT 60$: MOV #100000,U.PRM+2(R5) ;;;SET UNRECOVERABLE ERROR BIC #100,(R3) ;;;CLEAR INTERRUPT ENABLE BR 160$ ;;; 70$: MOV 6(R3),-(SP) ;;;GET CURRENT BLOCK NUMBER CMPB U.BUF+1(R5),1(R3) ;;;MOVING IN FINAL DIRECTION? BNE 80$ ;;;IF NE NO CMP (SP),U.PRM(R5) ;;;BLOCK NUMBER MATCH? BEQ 130$ ;;;IF EQ YES 80$: BIT #4000,(R3) ;;;MOVING IN FORWARD DIRECTION? BEQ 90$ ;;;IF EQ YES ADD #2,(SP) ;;;ADD TURN AROUND BIAS CMP U.PRM(R5),(SP)+ ;;;TURN AROUND NECESSARY? BR 100$ ;;; 90$: SUB #2,(SP) ;;;SUBTRACT TURN AROUND BIAS CMP (SP)+,U.PRM(R5) ;;;TURN AROUND NECESSARY? 100$: BLE 120$ ;;;IF LE NO TST -(R3) ;;;POINT TO ERROR REGISTER 110$: TST (R3)+ ;;;POINT TO COMMAND REGISTER DECB RTTBL+1(R4) ;;;DRIVE HUNG? BLT 60$ ;;;IF LT YES MOV #4000,-(SP) ;;;GET DIRECTION BIT BIC (R3),(SP) ;;;.NOT.COMMAND REGISTER.AND.DIRECTION B BIC #4000,(R3) ;;;.NOT.DIRECTION BIT.AND.COMMAND REGIST BIS (SP)+,(R3) ;;;DIRECTION BIT.OR.COMMAND REGISTER 120$: INC (R3) ;;;CONTINUE SEARCH MOV U.SCB(R5),R4 ;;;RETREIVE SCB ADDRESS BR 140$ ;;; 130$: TST (SP)+ ;;;REMOVE BLOCK NUMBER FROM STACK MOV U.SCB(R5),R4 ;;;RETRIEVE ADDRESS OF SCB BICB #S3.SIP,S.ST3(R4) ;;;RESET SEARCH IN PROGRESS MOV U.BUF(R5),(R3) ;;;START READ/WRITE FUNCTION 140$: MOV (SP)+,R3 ;;;RESTORE R3 BIS #S2.ACT,S.ST2(R4) ;;;SET I/O ACTIVE FLAG RETURN ;;; 150$: BICB #100,(R3) ;;;CLEAR INTERRUPT ENABLE TST (R3) ;;;ANY ERRORS? BPL 160$ ;;;IF PL NO ERRORS MOV -(R3),U.PRM+2(R5) ;;;SAVE ERROR STATUS 160$: MOV (SP)+,R3 ;;;RESTORE R3 CALL $FORK ;;;CREATE A SYSTEM PROCESS MOV R4,R3 ;COPY CONTROLLER INDEX MOV U.SCB(R5),R4 ;GET ADDRESS OF STATUS CONTROL BLOCK MOV S.CSR(R4),R2 ;GET ADDRESS OF COMMAND REGISTER MOV #IS.SUC&377,R0 ;ASSUME SUCCESSFUL COMPLETION MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION CALL? 165$: BNE 180$ ;IF NE YES MOV U.PRM+2(R5),R1 ;RETREIVE ERROR STATUS BEQ 180$ ;IF EQ SUCCESS CALL $DVERR ;LOG DEVICE ERROR BIT #63000,R1 ;RECOVERABLE ERROR? BEQ 170$ ;IF EQ NO DECB RTTBL(R3) ;ANY MORE RETRIES? BLE 170$ ;IF LE NO MOVB #8.,RTTBL+1(R3) ;RESET ROCK COUNT JMP 30$ ;TRY AGAIN 170$: MOV #IE.WLK&377,R0 ;ASSUME DRIVE WRITE LOCKED BIT #10000,R1 ;DRIVE WRITE LOCKED? BNE 180$ ;IF NE YES MOV #IE.VER&377,R0 ;UNRECOVERABLE ERROR 180$: MOV S.PKT(R4),R1 ;RETREIVE I/O PACKET ADDRESS BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION CALL? BEQ 187$ ;IF EQ NO CALL $CRPAS ;PASS UNIBUS DEVICE REGISTERS 187$: MOV U.CNT(R5),R1 ;GET ORIGINAL BYTE COUNT ADD 2(R2),R1 ;CALCULATE NUMBER OF BYTES TRANSFERED ADD 2(R2),R1 ; 190$: MOVB #11,(R2) ;STOP TAPE MOTION MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT 195$: CALL $IODON ;FINISH I/O OPERATION JMP DTINI ;GO AGAIN .DSABL LSB .END